package o2o.business.dispatch;


import com.jinyou.utils.common.*;
import o2o.cache.agent.AgentOrderOverTimeMemory;
import o2o.cache.agent.CityAgentMemory;
import o2o.cache.agent.PostmanAgentRelationMemory;
import o2o.cache.order.OrderInfoMemory;
import o2o.cache.order.postman.PostmanOrderMemoryMan;
import o2o.cache.postman.CityPostmanMemory;
import o2o.cache.postman.PostmanPositionMemory;
import o2o.cache.sys.SysConfigDepositMemory;
import o2o.cache.user.UserInfoMemory;
import o2o.cache.wallet.UserWalletMemory;
import o2o.dao.PO.agent.CityAgent;
import o2o.dao.PO.agent.OrderOverTimeInfo;
import o2o.dao.PO.common.ResultInfo;
import o2o.dao.PO.common.UserType;
import o2o.dao.PO.order.ORDER_STATUS;
import o2o.dao.PO.order.ORDER_TYPE;
import o2o.dao.PO.order.OrderInfo;
import o2o.postman.model.CityPostman;
import o2o.dao.PO.postman.POSTMAN_WORK_STATUS;
import o2o.dao.PO.postman.PostmanPositionInfo;
import o2o.dao.PO.user.UserInfo;
import o2o.dao.PO.wallet.UserWallet;
import o2o.web.actions.order.OrderMan;
import o2o.system.data.SYS_SETTINGS;

import java.util.ArrayList;
import java.util.List;

// 订单指派
// 1. 获取该范围内所有开工骑手，按距离最近的排序后
// 2. 遍历上一步获取的所有的骑手，是否有骑手进行中订单是空的
// 3. 如果有，直接指派
// 4. 如果所有骑手都有订单，进入下一步
// 5. 遍历1中得到的骑手，计算每个骑手，最早的订单与当前订单的方向夹角及骑手距离当前订单和最早订单的距离。夹角小于45度的，并且新距离小于最早订单的距离的骑手，记录下来
// 6. 将第5步中所有的骑手，按新距离排序
// 7. 遍历6中得到的骑手，判读骑手进行中是否订单量是否达到了最大值，如果未达到直接指派
// 8. 如果所有骑手都达到了上线，等待下一轮指派

// 距离商家的距离、距离用户距离、夹角、订单量  权重
public class DispatchPostmanBusiness {
    public static ResultInfo dispatch(String orderNo,
                                      String opUsername) {
//    }
//    public static boolean dispatch(String orderNo,
//                                   String opUsername) {
        OrderInfo orderInfo = OrderInfoMemory.getInstance().getOrderInfo(orderNo);
        if (null == orderInfo) {
//            return true;
            System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--订单信息不存在：" + orderNo);
            return new ResultInfo();
        }

        // 是不是预约单
        if (null != orderInfo.getIsAppointment() && 0 == 1 - orderInfo.getIsAppointment()) {
            // 是不是到了派单时间
            //如果到达预定时间前就可以看到
            //获取系统默认预约提醒时间，可以获取店铺的预约时间  1小时前的订单
            Long nowTime = DateUtils.getCurrTime();//当前时间
            Integer noticeTime = 60;// 默认没有设置的话60分钟
            // 获取商圈配置的时间
            Long agentId = orderInfo.getAgentId();
            if (ValidateUtil.isID(agentId)) {
                OrderOverTimeInfo orderOverTimeInfo = AgentOrderOverTimeMemory.getInstance().getAgentOrderOverTimeInfoByAgentId(agentId);
                if (null != orderOverTimeInfo && ValidateUtil.isAbsInteger(orderOverTimeInfo.getAppointPostmanTime())) {
                    noticeTime = orderOverTimeInfo.getAppointPostmanTime();
                }
            }
            if (ValidateUtil.isAbsInteger(noticeTime) && noticeTime < 5) {
                Integer postmanOverTime = orderInfo.getAgentPostmanOverTime();// 设置的要求骑手时长(postmanOverTime)
                Integer alertPostmanTime = orderInfo.getAlertPostmanTime();//  设置的骑手即将超时提醒时间[骑手接单-确认送达](alertPostmanTime)
                noticeTime = postmanOverTime + alertPostmanTime + 20;
            }
            if (orderInfo.getZiQuTime() - nowTime <= noticeTime * 60 * 1000) {
                //推送给骑手
            } else {
                // 不到时间
                System.out.println(DateUtils.getCurrentDateTime() + "   自动派单--不到时间：" + orderNo + ":" + orderInfo.getZiQuTime());
//                return false;
                return new ResultInfo("预约订单未到派单时间");
            }
        }

        // 订单状态是否满足要求
        if ((ORDER_STATUS.SHOP_SURE == orderInfo.getOrderStatus() && 0 == orderInfo.getIsZiQu())
                || (ORDER_STATUS.PAYED == orderInfo.getOrderStatus() && (null != orderInfo.getOrderType() && (0 == ORDER_TYPE.PAO_TUI - orderInfo.getOrderType() || 0 == ORDER_TYPE.DAI_GOU - orderInfo.getOrderType() || 0 == ORDER_TYPE.BANG_BAN - orderInfo.getOrderType() || 0 == ORDER_TYPE.HUO_YUN - orderInfo.getOrderType())))
                || (0 == ORDER_STATUS.SUBMIT - orderInfo.getOrderStatus() && (null != orderInfo.getOrderType() && 0 == ORDER_TYPE.SERVICE_LOCK - orderInfo.getOrderType()))) {

        } else {
//            return true;
            System.out.println(DateUtils.getCurrentDateTime() + "    自动派单--订单状态不满足要求：" + orderNo + ":" + orderInfo.getOrderStatus());
            return new ResultInfo();
        }

        // 订单经纬度是否符合要求
        if (ValidateUtil.isNotLatLng(orderInfo.getLat(), orderInfo.getLng())) {
//            return true;
            System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--订单信息经纬度为空：" + orderInfo.getLat() + "," + orderInfo.getLng());
            return new ResultInfo();
        }
        // 获取订单所属商圈
        Long agentId = orderInfo.getAgentId();
        if (ValidateUtil.isNotID(agentId)) {
            // todo 不是按商圈的，根据经纬度处理
            System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--商圈id为空：" + orderNo);
//            return true;
            return new ResultInfo();
        }

        CityAgent agentInfo = CityAgentMemory.getInstance().getById(agentId);
        if (null == agentInfo) {
//            return true;
            System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--商圈信息不存在：" + orderNo);
            return new ResultInfo();
        }
        // 商圈最大距离
        Integer agentRang = agentInfo.getRang();
        if (ValidateUtil.isNotAbsInteger(agentRang)) {
            agentRang = SYS_SETTINGS.DELIVERY_RANGE;
            if (ValidateUtil.isNotAbsInteger(agentRang)) {
                agentRang = 5;
            }
        }
        // 获取该商圈所有骑手
        List<String> pUserList = PostmanAgentRelationMemory.getInstance().listOfAgentId(agentId);
        if (!ValidateUtil.isAbsList(pUserList)) {
            // 该商圈没有骑手
            System.out.println("该商圈没有骑手:" + orderInfo.getOrderNo() + "," + orderInfo.getAgentId());
//            return false;
            return new ResultInfo("该商圈没有骑手");
        }

        // 符合条件骑手
        List<DispatchInfo> disList = new ArrayList<>();
        // 无符合条件骑手时的备用骑手
        List<DispatchInfo> usList = new ArrayList<>();
        // 遍历骑手
        for (int i = 0; i < pUserList.size(); i++) {
            String username = pUserList.get(i);
            if (ValidateUtil.isNull(username)) {
                continue;
            }

            // 获取骑手信息
            CityPostman postman = CityPostmanMemory.getInstance().getPostman(username);
            if (null == postman) {
                continue;
            }

            // 骑手的位置信息
            PostmanPositionInfo positionInfo = PostmanPositionMemory.getInstance().get(postman.getId());
            if (null == positionInfo) {
                System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--骑手位置信息不存在：" + orderNo + "；username:" + username + ";postmanId:" + postman.getId());
                continue;
            }

            // 经纬度是否有效
            if (ValidateUtil.isNotLatLng(positionInfo.getLat(), positionInfo.getLng())) {
                System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--骑手位置信息不完整：" + orderNo + "；username:" + username);
                continue;
            }

            // 验证骑手的基本信息
            if (!isUsefulPostmanBase(postman, agentId, orderNo)) {
                continue;
            }
            DispatchInfo dispatchInfo = new DispatchInfo();
            // 骑手离订单的距离(米)
            double distance = Geohash.distance(positionInfo.getLat(), positionInfo.getLng(), orderInfo.getLat(), orderInfo.getLng());
            // 距离是否超出商圈范围
            if (JYMathDoubleUtils.sub(distance, agentRang * 1000) > 0) {
                System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--距离是否超出商圈范围：" + orderNo + "；" + distance);
                continue;
            }
            dispatchInfo.setPostmanInfo(postman);
            dispatchInfo.setDistance(distance);

            // 备用骑手
            usList.add(dispatchInfo);

            // 获取骑手进行中的一个订单
            List<OrderInfo> orderList = PostmanOrderMemoryMan.listOfPostmanIng(postman.getUsername(), 0l, 1);
            if (ValidateUtil.isAbsList(orderList)) {
                OrderInfo postmanOrder = orderList.get(0);
                if (null != postmanOrder && ValidateUtil.isLatLng(postmanOrder.getLat(), postmanOrder.getLng())) {
                    // 获取骑手最后订单与新订单夹角
                    double angle = AngleUtils.getSubAngle(positionInfo.getLat(), positionInfo.getLng(),
                            postmanOrder.getLat(), postmanOrder.getLng(),
                            orderInfo.getLat(), orderInfo.getLng());

                    // todo 夹角大于45度
                    if (angle > 45) {
//                        System.out.println("夹角大于45：" + orderNo + "," + angle);
                        System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--夹角大于45：" + orderNo + "；角度：" + angle + ";骑手：" + postman.getUsername());
                        continue;
                    }
                    dispatchInfo.setAngle(angle);
                }
            }


            disList.add(dispatchInfo);
        }

        if (!ValidateUtil.isAbsList(disList)) {
            // 无符合条件骑手，并且只有一个备用骑手时，直接派个备用骑手（因为有商圈只有一个骑手）
            if (ValidateUtil.isAbsList(usList) && usList.size() == 1) {
                if (null != usList.get(0) && null != usList.get(0).getPostmanInfo()) {
                    OrderMan.setOrderPostman(orderInfo.getOrderNo(), usList.get(0).getPostmanInfo(), opUsername);
//                    return true;
                    return new ResultInfo();
                }
            }
//            return false;
            System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--没有可选择的骑手：" + orderNo);
            return new ResultInfo("没有可选择的骑手");
        }
        // 将骑手按距离最近的最前面排序
        JYListSort.sort(disList, "distance");

        // 骑手最多可接单数量
        int postmanMaxOrderCount = 10;
        boolean isAgentSettings = false;// 是否使用商圈的设置
        if (ValidateUtil.isID(agentId)) {
            OrderOverTimeInfo overTimeInfo = AgentOrderOverTimeMemory.getInstance().getAgentOrderOverTimeInfoByAgentId(agentId);
            if (null != overTimeInfo) {
                postmanMaxOrderCount = overTimeInfo.getPostmanMaxOrderNum();
                isAgentSettings = true;
            }
        }
        if (!isAgentSettings && null != SYS_SETTINGS.POSTMAN_MAX_ORDER_NUM && SYS_SETTINGS.POSTMAN_MAX_ORDER_NUM > 0) {
            postmanMaxOrderCount = SYS_SETTINGS.POSTMAN_MAX_ORDER_NUM;
        }

        // 遍历骑手列表
        for (int i = 0; i < disList.size(); i++) {
            DispatchInfo dispatchInfo = disList.get(i);
            if (null == dispatchInfo) {
                continue;
            }
            CityPostman postman = dispatchInfo.getPostmanInfo();
            if (null == postman) {
                continue;
            }
            if (ValidateUtil.isNull(postman.getUsername())) {
                continue;
            }
            // 获取骑手订单量
            Integer orderCount = PostmanOrderMemoryMan.getPostmanIngOrderCount(postman.getUsername());
            if (ValidateUtil.isNotAbsInteger(orderCount)) {
                // 该骑手没有订单
                // 所需要的骑手
                OrderMan.setOrderPostman(orderInfo.getOrderNo(), postman, opUsername);
                // 结束
//                return true;
                return new ResultInfo();
            }

            // 骑手可接单量
            if (postmanMaxOrderCount > 0 && orderCount >= postmanMaxOrderCount) {
                System.out.println("超出骑手可接单量：" + orderInfo.getOrderNo() + "," + postmanMaxOrderCount + "," + orderCount);
                continue;
            } else {
                // 分配
                OrderMan.setOrderPostman(orderInfo.getOrderNo(), postman, opUsername);
//                return true;
                return new ResultInfo();
            }
        }

        // 无符合条件骑手，并且只有一个备用骑手时，直接派个备用骑手（因为有商圈只有一个骑手）
        if (ValidateUtil.isAbsList(usList) && usList.size() == 1) {
            System.out.println("有一个备用骑手：" + orderNo);
            if (null != usList.get(0) && null != usList.get(0).getPostmanInfo()) {
                OrderMan.setOrderPostman(orderInfo.getOrderNo(), usList.get(0).getPostmanInfo(), opUsername);
//                return true;
                return new ResultInfo();
            } else {
                System.out.println("一个备用骑手无效：" + orderNo);
            }
        }

        System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--没有可选择的骑手：" + orderNo);
        return new ResultInfo("骑手都无效");
    }


    private static boolean isUsefulPostmanBase(CityPostman postman, Long agentId, String orderNo) {
        if (null == postman) {
            return false;
        }

        //0 锁定  1未锁定
        if (null != postman.getIsLock() && 0 == 1 - postman.getIsLock()) {
            System.out.println(DateUtils.getCurrentDateTime() + "  " + orderNo + " 已被锁定，无法接单," + postman.getUsername());
            return false;
        }

        if (0 == POSTMAN_WORK_STATUS.POSTMAN_OFF_WORK - postman.getIsWork() || 0 == POSTMAN_WORK_STATUS.POSTMAN_BUSY - postman.getIsWork()) {
            // 未上班、或者忙碌的骑手不进行自动派单
            System.out.println(DateUtils.getCurrentDateTime() + "  " + orderNo + "  骑手已下班：" + postman.getUsername() + "," + postman.getIsWork());
            return false;
        }

        if (null != SYS_SETTINGS.POSTMAN_MUST_VERIFY && 0 == 1 - SYS_SETTINGS.POSTMAN_MUST_VERIFY
                && (null == postman.getIsVerify() || 0 != 1 - postman.getIsVerify())) {
//            return AjaxResult.errorResult("您尚未通过认证，请先去认证");
            System.out.println(DateUtils.getCurrentDateTime() + "  " + orderNo + "  骑手未认证：" + postman.getUsername());
            return false;
        }
        UserInfo user = UserInfoMemory.getInstance().getUserInfo(postman.getUsername());
        if (null == user) {
            System.out.println(DateUtils.getCurrentDateTime() + "  " + orderNo + "  骑手在用户信息中不存在:" + postman.getUsername());
            return false;
        }
        if (null != SYS_SETTINGS.POSTMAN_MUST_VERIFY_FACE && 0 == 1 - SYS_SETTINGS.POSTMAN_MUST_VERIFY_FACE) {
            if (null != user.getIsCert() && 0 == 1 - user.getIsCert()) {
                //已认证
            } else {
                System.out.println(DateUtils.getCurrentDateTime() + "  " + orderNo + "  自动派单--骑手未实名认证：" + postman.getUsername());
//                return AjaxResult.errorResult("未通过实名认证，请先去认证");
                return false;
            }
        }

        // 配送员可抢单数量
        boolean isAgentSettings = false;// 是否使用商圈的设置
        Integer postmanCanGrabOrder = -1;// 配送员可抢单数量
        if (ValidateUtil.isID(agentId)) {
            OrderOverTimeInfo overTimeInfo = AgentOrderOverTimeMemory.getInstance().getAgentOrderOverTimeInfoByAgentId(agentId);
            if (null != overTimeInfo) {
                postmanCanGrabOrder = overTimeInfo.getPostmanCanGrabOrder();
                isAgentSettings = true;
            }
        }
        if ((isAgentSettings && postmanCanGrabOrder > 0) || (!isAgentSettings && null != SYS_SETTINGS.POSTMAN_CAM_GRAB_ORDER && SYS_SETTINGS.POSTMAN_CAM_GRAB_ORDER > 0)) {
            int count = PostmanOrderMemoryMan.getPostmanIngOrderCount(user.getUsername());
            if (isAgentSettings) {
                if (count - postmanCanGrabOrder >= 0) {
//                return AjaxResult.errorResult("您有未完成订单，无法继续抢单");
                    System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--有未完成订单，无法继续派单：" + orderNo + ";" + postman.getUsername() + ";count:" + count + ";postmanCanGrabOrder:" + postmanCanGrabOrder);
                    return false;
                }
            } else {
                if (count - SYS_SETTINGS.POSTMAN_CAM_GRAB_ORDER >= 0) {
//                return AjaxResult.errorResult("您有未完成订单，无法继续抢单");
                    System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--有未完成订单，无法继续派单2：" + orderNo + ";" + postman.getUsername() + ";count:" + count + ";postmanCanGrabOrder:" + SYS_SETTINGS.POSTMAN_CAM_GRAB_ORDER);
                    return false;
                }
            }
        }

//        if (null != SYS_SETTINGS.POSTMAN_CAM_GRAB_ORDER && SYS_SETTINGS.POSTMAN_CAM_GRAB_ORDER > 0) {
//            int count = OrderInfoMemory.getInstance().getPostmanIngOrderCount(user.getUsername());
//            if (count - SYS_SETTINGS.POSTMAN_CAM_GRAB_ORDER >= 0) {
////                return AjaxResult.errorResult("您有未完成订单，无法继续抢单");
//                return false;
//            }
//        }

        if (null != SYS_SETTINGS.POSTMAN_MUST_DEPOSIT && 0 == 1 - SYS_SETTINGS.POSTMAN_MUST_DEPOSIT) {
            // 必须缴纳
            //验证押金金额是否满足
            UserWallet userWallet = UserWalletMemory.getInstance().getWallet(user.getUsername());
            if (null == userWallet) {
//                return AjaxResult.errorResult("您还未缴纳押金，请先缴纳押金");
                System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--未缴纳押金：" + postman.getUsername() + ";orderno:" + orderNo);
                return false;
            }
            if (null == userWallet.getDepositMoney() || userWallet.getDepositMoney() <= 0) {
//                return AjaxResult.errorResult("您还未缴纳押金，请先缴纳押金！");
                System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--未缴纳押金2：" + postman.getUsername() + ";orderno:" + orderNo);
                return false;
            }
            //必须缴纳的押金金额
            Double money = SysConfigDepositMemory.getInstance().getByType(UserType.POSTMAN);
            if (null == money) {
                money = 0d;
            }

            if (JYMathDoubleUtils.sub(userWallet.getDepositMoney(), money) < 0) {
//                return AjaxResult.errorResult("您缴纳的押金不足，请先缴纳押金");
                System.out.println(DateUtils.getCurrentDateTime() + "  自动派单--押金不足：" + postman.getUsername() + ";orderno:" + orderNo);
                return false;
            }
        }


        return true;
    }

}
